package org.linlinjava.litemall.wx.service;

import cn.hutool.core.util.ObjectUtil;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.notify.PosPushSender;
import org.linlinjava.litemall.core.payment.DefaultCurType;
import org.linlinjava.litemall.core.payment.PaymentResponseCode;
import org.linlinjava.litemall.core.payment.paypal.service.impl.GoodsPaypalServiceImpl;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.LitemallAccountBookFormDto;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderHandleOption;
import org.linlinjava.litemall.db.util.OrderStatusUtil;
import org.linlinjava.litemall.wx.util.RewardsUtils;
import org.linlinjava.litemall.wx.util.WxResponseEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.stream.Collectors;

/**
 * @author ：stephen
 * @date ：Created in 2020/4/9 10:41
 * @description：TODO
 */
@Service
public class WxCardPayService {
    @Autowired
    private LitemallOrderService litemallOrderService;
    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;
    @Autowired
    private LitemallOrderGoodsService litemallOrderGoodsService;
    @Autowired
    private LitemallGiftCardUserLogService litemallGiftCardUserLogService;

    @Autowired
    private LitemallGiftCardOrderService litemallGiftCardOrderService;
    @Autowired
    private LitemallAccountBookService litemallAccountBookService;
    @Autowired
    private LitemallIntegralLogService litemallIntegralLogService;

    @Autowired
    private NoticeHelper noticeHelper;
    @Autowired
    private PosPushSender posPushSender;

    @Autowired
    private RewardsUtils rewardsUtils;


    @Autowired
    private GoodsPaypalServiceImpl paypalService;

    @Autowired
    private WxCloverPayService wxCloverPayService;
    /**
     * 礼物卡支付订单
     * @param userId
     * @param body
     * @return
     */
    @Transactional
    public Object pay(Integer userId, String body){
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        Integer cardId = JacksonUtil.parseInteger(body, "cardId");
        if(orderId == null){
            return ResponseUtil.badArgument(WxResponseEnum.BAD_ARGUMENT_ORDERID);
        }
        if(cardId == null){
            return ResponseUtil.badArgument(WxResponseEnum.BAD_ARGUMENT_CARDID);
        }

        LitemallOrder order = litemallOrderService.findById(orderId);
        // 检测订单是否能够支付
        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isPay()) {
            return ResponseUtil.fail(PaymentResponseCode.ORDER_INVALID_OPERATION, "订单不能支付");
        }

        LitemallGiftCardUser card = litemallGiftCardUserService.findById(cardId);
        if(card == null || !card.getUserId().equals(userId)){
            return ResponseUtil.badArgument(WxResponseEnum.IS_NULL_CARD);
        }
        if(card.getStatus() == 2){
            return ResponseUtil.badArgument(WxResponseEnum.GIFT_CARD_DISABLED);
        }
        if(card.getAmount().compareTo(order.getActualPrice()) < 0){
            return ResponseUtil.badArgument(WxResponseEnum.NOT_ENOUGH_AMOUNT);
        }


        //创建礼物卡订单
        LitemallGiftCardOrder giftCardOrder = new LitemallGiftCardOrder();
        giftCardOrder.setCurrency(DefaultCurType.CAD.getType());
        giftCardOrder.setAmount(order.getActualPrice());
        giftCardOrder.setUserId(userId);
        giftCardOrder.setCardNumber(card.getCardNumber());
        giftCardOrder.setGiftCardId(card.getGiftCardId());
        giftCardOrder.setShopId(order.getShopId());
        giftCardOrder.setAddUserId(userId);

        giftCardOrder.setPayType(Constants.ORDER_PAY_TYPE_CARD);
        giftCardOrder.setPayStatus((byte) 2);
        giftCardOrder.setPayTime(LocalDateTime.now());
        giftCardOrder.setOrderId(orderId);
        litemallGiftCardOrderService.add(giftCardOrder);
        //是否第一次消费
        LitemallIntegralLog rewardInConsum = rewardsUtils.getRewardInConsum(userId);
        if(ObjectUtil.isNotNull(rewardInConsum)){
            rewardInConsum.setUseType(9);
            rewardInConsum.setGoodsName(litemallOrderGoodsService.queryByOid(orderId).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()));
            rewardInConsum.setOrderId(orderId);
            litemallIntegralLogService.add(rewardInConsum);
        }

        // 检查这个订单是否已经处理过
        if (OrderStatusUtil.isPayStatus(order) || order.getPayId() != null) {
            return ResponseUtil.fail(PaymentResponseCode.PAYMENT_FAIL, order.getOrderSn() + "The order has been processed successfully!");
        }

        BigDecimal point =  paypalService.presentPoint(orderId,null);
        //用户 等级会员的提升
        paypalService.upgradeUserLevel(orderId);

        //记录消费情况
        LitemallGiftCardUserLog log = saveLog(giftCardOrder.getId(),order, card, userId, "消费",point);

        order.setPayType(Constants.ORDER_PAY_TYPE_CARD);
        order.setCurrency(DefaultCurType.CAD.getType());
        order.setPayTime(LocalDateTime.now());
//        order.setOrderStatus(OrderUtil.STATUS_PAY);
        order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);
        order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
        order.setPayId(String.valueOf(log.getId()));        //将消费日志id作为支付id
        order.setTransationId(String.valueOf(log.getId())); //将消费日志id作为transation id
        litemallOrderService.updateById(order);
        //更新订单
        /*if (litemallOrderService.updateWithOptimisticLocker(order) == 0) {
            // 这里可能存在这样一个问题，用户支付和系统自动取消订单发生在同时
            // 如果数据库首先因为系统自动取消订单而更新了订单状态；
            // 此时用户支付完成回调这里也要更新数据库，而由于乐观锁机制这里的更新会失败
            // 因此，这里会重新读取数据库检查状态是否是订单自动取消，如果是则更新成支付状态。
            order = litemallOrderService.findBySn(order.getOrderSn());
            int updated = 0;
            if (OrderStatusUtil.isCancelStatus(order)) {
                order.setPayTime(LocalDateTime.now());
//                order.setOrderStatus(OrderUtil.STATUS_PAY);
                order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);
                order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
                updated = litemallOrderService.updateWithOptimisticLocker(order);
            }

            // 如果updated是0，那么数据库更新失败
            if (updated == 0) {
                return ResponseUtil.updatedDateExpired();
            }
        }*/



        //更新卡余额
        LitemallGiftCardUser giftCard = new LitemallGiftCardUser();
        giftCard.setAmount(card.getAmount().subtract(order.getActualPrice()));
        giftCard.setId(card.getId());
        giftCard.setStatus(1);
        if(litemallGiftCardUserService.updateWithOptimisticLocker(giftCard, card.getUpdateTime()) == 0){
            return ResponseUtil.updatedDateExpired();
        }

        //添加收款记录
    	LitemallAccountBookFormDto form = new LitemallAccountBookFormDto();
    	Integer shopId = order.getShopId();
    	form.setShopId(shopId);
    	form.setRecordType(0);
    	form.setRecordDate(LocalDateTime.now());
    	form.setAmount(order.getActualPrice());
    	form.setRemark("app order");
    	form.setSourceType(Constants.BOOK_SOURCE_TYPE_ORDER);
    	litemallAccountBookService.create(shopId, form);

//        notifyService.notifyMail("新订单", order.toString());
        //发送订单支付成功通知
        noticeHelper.noticeUser(Constants.MSG_TYPE_ORDER,"order payment", order.getOrderSn()+"order payment success", userId, order);
        //发送已支付订单到pos系统，门店开始制作商品
//        noticeHelper.noticeShop(Constants.MSG_TYPE_ORDER, JSON.toJSONString(order), order.getShopId());
        //发送礼物卡消费通知
        noticeHelper.noticeUser( Constants.MSG_TYPE_OTHER,"gift card consumption", "Your card"+card.getCardNumber()+"consume：$"+order.getActualPrice(), userId, giftCard);
        //推送厨房端
    	posPushSender.pushAll(order.getShopId(), Constants.ORDER_PUSH_TYPE_PAID, null);
        return ResponseUtil.ok();
    }

    /**
     * 记录日志并返回
     * @param order
     * @param card
     * @param userId
     * @return
     */
    @Transactional
    public LitemallGiftCardUserLog saveLog( Integer giftCardUserOrderId,LitemallOrder order, LitemallGiftCardUser card, Integer userId, String content,BigDecimal points){
        LitemallGiftCardUserLog log = new LitemallGiftCardUserLog();
        log.setOrderId(giftCardUserOrderId);
        log.setAmount(order.getActualPrice());
        log.setAddUserId(userId);
        log.setShopId(order.getShopId());
        log.setType(Constants.LOG_GIFTCARD_CONSUME);
        log.setCardNumber(card.getCardNumber());
        log.setChangePoints(points);
        //用户
        log.setBalance(card.getAmount().subtract(order.getActualPrice()));
        log.setCardUserId(card.getId());
        log.setContent(content);
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        log.setChangePoints(order.getPoints());
        litemallGiftCardUserLogService.add(log);
        return log;
    }

}
